import numpy as np

class Task(object):

    gantt = [] #
    schedule_events = None
    event_tick = -1

    def __init__(self, env, task_config):
        self.env = env # env = simpy.Enviorment()
        self.task_id = task_config.task_id
        self.task_type = task_config.task_type # 通风/通电/冲氧/加油
        self.type_name = task_config.type_name
        self.worker_type = task_config.worker_type
        # self.event = self.node.event

        # 对应的工人执行
        self.worker = None
        self.process = None
        # 执行参数
        self.started = False
        self.finished = False
        self.started_timestamp = -1
        self.finished_timestamp = -1
        self.__duration_Time = task_config.duration

        # task dependency
        self._ready = False
        self.parents = []
        self.child = None
        # 表示当前的task位于task graph 的第几层
        # 可以发生变动
        self._layer = task_config.init_layer
        self._init_layer = self._layer
        #plane
        self.plane = None

    def attach(self,plane):
        self.plane = plane

    @property
    def id(self):
        return self.plane.id+'-'+self.task_id

    @property
    def layer(self):
        """定义 layer: 表示task的层次信息"""
        if self.ready:
            self._layer = 0
            return self._layer
        # for task in self.child:
        self._layer = max([task.layer for task in self.parents]) + 1

        return self._layer

    def reset(self):
        self.env = self.plane.env
        # 对应的工人执行
        self.worker = None
        self.process = None
        # 执行参数
        self.started = False
        self.finished = False
        self.started_timestamp = -1
        self.finished_timestamp = -1

        self._layer = self._init_layer

    @classmethod
    def log_gantt(cls)->list:

        return cls.gantt

    @classmethod
    def event_init(cls,events:list):
        cls.schedule_events = events


    # @property # id 属性
    # def id(self) -> str:
    #     return str(self.plane.id) + '-' + str(self.task_id)

    @property  # id 属性
    def duration(self) -> int:
        # return self.worker.get_duration(self.task_type)
        # todo: impliments task duration
        # 和具体工人有关
        if not self.started:
            return self.__duration_Time

        elif self.finished:
            return 0

        return int(self.__duration_Time +self.started_timestamp - self.env.now)

    def do_work(self):
        # self.cluster.waiting_tasks.remove(self)
        # self.cluster.running_tasks.append(self)
        # self.machine.run(self)

        # self.started_timestamp = self.env.now
        yield self.env.timeout(self.duration)

        self.finished = True
        self.finished_timestamp = self.env.now
        # task_type,node_id,plane_id,woker_id,start,end
        Task.gantt.append([str(self),self.task_type,self.worker_type,\
                        self.worker.id,\
                           self.started_timestamp,self.finished_timestamp])
        # todo: print information
        # print(str(self),"+",self.worker.id,self.started_timestamp,self.finished_timestamp)
        self.__event_triggle()




    def __event_triggle(self):
        # todo: task 关联调度事件
        # if Task.event_tick < 0 or Task.event_tick < self.env.now:
            # 默认在同一时间的触发中，只能触发一次
        Task.schedule_events[0].succeed()
        Task.schedule_events[0] = self.env.event()
        Task.event_tick = self.env.now

    def schedule(self, worker):


        self.worker = worker
        # self.worker.run_task()
        self.started = True
        self.started_timestamp = self.env.now
        self.process = self.env.process(self.do_work())

    def __str__(self) -> str:
        return "task:["+self.plane.id+"-"+str(self.task_id)+","+self.task_type+"]"

    @property
    def ready(self):

        if len(self.parents) == 0:
            return True

        # __ready = False
        for parent in self.parents:

            if not parent.finished:
                return False

        return True

class Task_Config(object):

    def __init__(self,task_id,task_type,type_name,duration,worker_type,layer):
        self.task_id = task_id
        self.task_type = task_type
        self.type_name = type_name
        self.duration = duration
        self.worker_type = worker_type
        self.init_layer = layer


